package com.sencorsta.ids.core.application.zone;

import java.util.Map;
import java.util.Queue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;

import com.sencorsta.ids.core.application.master.MasterClient;
import com.sencorsta.ids.core.application.proxy.ProxyClient;
import com.sencorsta.ids.core.configure.SysConfig;
import com.sencorsta.ids.core.log.Out;
import com.sencorsta.ids.core.tcp.opensocket.OpenMessage;
import com.sencorsta.ids.core.tcp.socket.protocol.RpcMessage;
import com.sencorsta.ids.core.tcp.socket.server.IdsThreadFactory;

public abstract class Zone {

    private final static AtomicInteger UUID = new AtomicInteger(0);
    private final int id;
    private final String sub;

    public Map<String, ZoneUser> zoneUsers = new ConcurrentHashMap<>();

    protected final long createTime = System.currentTimeMillis();

    public Zone() {
        this.id = newId();
        sub = String.format("/ZONE/%s/%d", MasterClient.getInstance().localServer.sid, this.id);
    }

    protected int newId() {
        return UUID.incrementAndGet();
    }

    public int getId() {
        return this.id;
    }

    public void enter(ZoneUser zoneUser) {
        zoneUsers.put(zoneUser.userId, zoneUser);
        zoneUser.subscribe(sub);
        zoneUser.zone = this;
    }

    public void leave(ZoneUser zoneUser) {
        zoneUsers.remove(zoneUser.userId);
        zoneUser.unSubscribe(sub);
        zoneUser.zone = null;
    }

    /**
     * 房间中的所有玩家接收消息（大于5人走管道机制）
     */
    public void broadcast(RpcMessage msg, String type) {
        if (zoneUsers.size() <= 5) {
            for (ZoneUser zoneUser : zoneUsers.values()) {
                RpcMessage newMsg= null;
                try {
                    newMsg = (RpcMessage) msg.clone();
                } catch (CloneNotSupportedException e) {
                    e.printStackTrace();
                }
                newMsg.userId=zoneUser.userId;
                zoneUser.sendMsg(newMsg);
            }
        } else {
            ProxyClient.broadcast(msg, type, sub);
        }
    }

    public int getZoneUsersCount() {
        return zoneUsers.size();
    }

    private static final int __AVAILABLEP__ROCESSORS__ = SysConfig.getInstance().getInt("client.availableProcessors", Runtime.getRuntime().availableProcessors());
    private ExecutorService __EXECUTOR__ = Executors.newFixedThreadPool(__AVAILABLEP__ROCESSORS__ * 2 + 1,new IdsThreadFactory("Zone"+getId()));

//    private Queue<Runnable> actQueue = new ConcurrentLinkedQueue<Runnable>();

    public void addEvent(Runnable act) {
//		if (actQueue.add(act)==false){
//			Out.debug("addEvent size满了:",actQueue.size());
//			onBusy();
//		}else {
//
//			if (actQueue.size()>10000){
//				Out.warn("addEvent size过多:"+actQueue.size());
//			}
//	 	}
        __EXECUTOR__.execute(act);
    }

    public void execute() {
//		while (!actQueue.isEmpty()) {
//			Runnable act = actQueue.poll();
//			act.run();
//		}
        update();
    }

    public abstract void update();

    //public abstract void onBusy();

    public void disponse() {
        if (zoneUsers.size() > 0) {
//			for (ZoneUser zoneUser : zoneUser.values()) {
//				zoneUser.unsubscribe(sub);
//			}
            zoneUsers.clear();
        }
    }

}
